package service

import (
	"bytes"
	"context"
	"encoding/json"
	"github.com/elastic/go-elasticsearch/v7"
	"github.com/elastic/go-elasticsearch/v7/esapi"
	"log"
	"strconv"
	"strings"
	"sync"
	"user-server/basic/config"
	__ "user-server/basic/proto"
	"user-server/handler/model"
)

// server is used to implement helloworld.GreeterServer.
type Server struct {
	__.UnimplementedVideoServer
}

// SayHello implements helloworld.GreeterServer
func (s *Server) Video(_ context.Context, in *__.VideoAddReq) (*__.VideoAddResp, error) {

	video := model.Video{
		Title:       in.Title,
		Description: in.Description,
		CoverUrl:    in.CoverUrl,
		CategoryId:  int(in.CategoryId),
		TypeId:      int(in.TypeId),
		RegionId:    int(in.RegionId),
		Year:        int(in.Year),
	}

	if err := video.CreateVideo(); err != nil {
		return &__.VideoAddResp{
			Code: 400,
			Msg:  "视频信息创建失败",
		}, nil
	}

	return &__.VideoAddResp{
		Code: 200,
		Msg:  "视频添加成功",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) VideoReview(_ context.Context, in *__.VideoReviewReq) (*__.VideoReviewResp, error) {

	review := model.VideoReview{
		VideoId:  int(in.VideoId),
		Status:   int(in.Status),
		Reason:   in.Reason,
		ReviewId: int(in.ReviewId),
	}

	if err := review.CreateVideoReview(); err != nil {
		return &__.VideoReviewResp{
			Code: 400,
			Msg:  "视频审核不成功",
		}, nil
	}

	return &__.VideoReviewResp{
		Code: 200,
		Msg:  "视频审核成功",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) VideoList(_ context.Context, in *__.VideoListReq) (*__.VideoListResp, error) {

	var all []model.Video
	config.DB.Find(&all)

	return &__.VideoListResp{
		Code: 200,
		Msg:  "视频列表展示成功",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) VideoShow(_ context.Context, in *__.VideoShowReq) (*__.VideoShowResp, error) {

	var all model.Video
	config.DB.Where("id = ?", in.Id).First(&all)

	return &__.VideoShowResp{
		Code: 200,
		Msg:  "视频列表展示成功",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) EpisodeList(_ context.Context, in *__.EpisodeListReq) (*__.EpisodeListResp, error) {

	var all model.DramaEpisode
	config.DB.Find(&all)

	return &__.EpisodeListResp{
		Code: 200,
		Msg:  "剧集列表展示成功",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) HistoryAdd(_ context.Context, in *__.HistoryAddReq) (*__.HistoryAddResp, error) {

	history := model.UserHistory{
		UserId:    int(in.UserId),
		VideoId:   int(in.VideoId),
		EpisodeId: int(in.EpisodeId),
		Progress:  int(in.Progress),
	}

	if err := history.CreateHistory(); err != nil {
		return &__.HistoryAddResp{
			Code: 400,
			Msg:  "历史记录存储失败",
		}, nil
	}

	return &__.HistoryAddResp{
		Code: 200,
		Msg:  "历史记录存储成功",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) HistoryList(_ context.Context, in *__.HistoryListReq) (*__.HistoryListResp, error) {

	var all []model.UserHistory
	config.DB.Find(&all)

	return &__.HistoryListResp{
		Code: 200,
		Msg:  "历史记录查询成功",
	}, nil
}

var (
	r  map[string]interface{}
	wg sync.WaitGroup
)

// SayHello implements helloworld.GreeterServer
func (s *Server) Searches(_ context.Context, in *__.SearchesReq) (*__.SearchesResp, error) {

	page, _ := strconv.Atoi("page")
	if page <= 0 {
		page = 1
	}

	pageSize, _ := strconv.Atoi("page_size")
	switch {
	case pageSize > 100:
		pageSize = 100
	case pageSize <= 0:
		pageSize = 10
	}

	es, err := elasticsearch.NewDefaultClient()
	if err != nil {
		log.Fatalf("Error creating the client: %s", err)
	}

	// 1. Get cluster info
	//
	res, err := es.Info()
	if err != nil {
		log.Fatalf("Error getting response: %s", err)
	}
	defer res.Body.Close()
	// Check response status
	if res.IsError() {
		log.Fatalf("Error: %s", res.String())
	}
	// Deserialize the response into a map.
	if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
		log.Fatalf("Error parsing the response body: %s", err)
	}
	// Print client and server version numbers.
	log.Printf("Client: %s", elasticsearch.Version)
	log.Printf("Server: %s", r["version"].(map[string]interface{})["number"])
	log.Println(strings.Repeat("~", 37))

	// 2. Index documents concurrently
	//
	for i, title := range []string{"Test One", "Test Two"} {
		wg.Add(1)

		go func(i int, title string) {
			defer wg.Done()

			// Build the request body.
			data, err := json.Marshal(struct{ Title string }{Title: title})
			if err != nil {
				log.Fatalf("Error marshaling document: %s", err)
			}

			// Set up the request object.
			req := esapi.IndexRequest{
				Index:      "test",
				DocumentID: strconv.Itoa(i + 1),
				Body:       bytes.NewReader(data),
				Refresh:    "true",
			}

			// Perform the request with the client.
			res, err := req.Do(context.Background(), es)
			if err != nil {
				log.Fatalf("Error getting response: %s", err)
			}
			defer res.Body.Close()

			if res.IsError() {
				log.Printf("[%s] Error indexing document ID=%d", res.Status(), i+1)
			} else {
				// Deserialize the response into a map.
				var r map[string]interface{}
				if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
					log.Printf("Error parsing the response body: %s", err)
				} else {
					// Print the response status and indexed document version.
					log.Printf("[%s] %s; version=%d", res.Status(), r["result"], int(r["_version"].(float64)))
				}
			}
		}(i, title)
	}
	wg.Wait()

	log.Println(strings.Repeat("-", 37))

	// 3. Search for the indexed documents
	//
	// Build the request body.
	var buf bytes.Buffer
	query := map[string]interface{}{
		"query": map[string]interface{}{
			"match": map[string]interface{}{
				"title": "test",
			},
		},
	}
	if err := json.NewEncoder(&buf).Encode(query); err != nil {
		log.Fatalf("Error encoding query: %s", err)
	}

	// Perform the search request.
	res, err = es.Search(
		es.Search.WithContext(context.Background()),
		es.Search.WithIndex("test"),
		es.Search.WithBody(&buf),
		es.Search.WithTrackTotalHits(true),
		es.Search.WithPretty(),
	)
	if err != nil {
		log.Fatalf("Error getting response: %s", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		var e map[string]interface{}
		if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
			log.Fatalf("Error parsing the response body: %s", err)
		} else {
			// Print the response status and error information.
			log.Fatalf("[%s] %s: %s",
				res.Status(),
				e["error"].(map[string]interface{})["type"],
				e["error"].(map[string]interface{})["reason"],
			)
		}
	}
	return &__.SearchesResp{
		Code: 0,
		Msg:  "",
	}, nil
}

// SayHello implements helloworld.GreeterServer
func (s *Server) HeatCalculate(_ context.Context, in *__.HeatCalculateReq) (*__.HeatCalculateResp, error) {
	
	return &__.HeatCalculateResp{
		Code: 200,
		Msg:  "热度计算成功",
	}, nil
}
